package com.queming.service.user;

import com.auth0.jwt.JWT;
import com.auth0.jwt.algorithms.Algorithm;
import com.queming.core.config.SecurityConfig;
import com.queming.core.dto.TokenRequest;
import com.queming.core.dto.UserCreateDto;
import com.queming.core.dto.UserDto;
import com.queming.core.dto.UserUpdateDto;
import com.queming.core.entity.User;
import com.queming.core.exception.ExceptionType;
import com.queming.core.exception.BizException;
import com.queming.core.mapper.UserMapper;
import com.queming.core.respository.UserRepository;
import com.queming.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Optional;

/**
 * @author chencidiao
 * @date 2022/04/17 20:34
 **/
@Service
public class UserServiceImpl extends BaseService implements UserService {

    UserRepository userRepository;
    @Autowired
    public void setUserRepository(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    UserMapper userMapper;
    @Autowired
    public void setUserMapper(UserMapper userMapper) {
        this.userMapper = userMapper;
    }

    //密码加密器
    PasswordEncoder passwordEncoder;
    @Autowired
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
        this.passwordEncoder = passwordEncoder;
    }



    @Override
    public UserDto create(UserCreateDto userCreateDto) {
        checkUserName(userCreateDto.getUsername());
        User entity = userMapper.createEntity(userCreateDto);
        entity.setPassword(passwordEncoder.encode(entity.getPassword()));
        return userMapper.toDto(userRepository.save(entity));
    }


    @Override
    public User loadUserByUsername(String username)  {
        return super.findUserByUsername(username);
    }

    @Override
    public Page<UserDto> search(Pageable pageable) {
        return userRepository.findAll(pageable).map(userMapper::toDto);
    }

    @Override
    public UserDto get(String id) {
        return userMapper.toDto(getById(id));
    }

    private User getById(String id){
        Optional<User> user = userRepository.findById(id);
        if (!user.isPresent()){
            throw new BizException(ExceptionType.USER_UNKNOW_ERROR);
        }
        return user.get();
    }

    @Override
    public UserDto update(String id, UserUpdateDto userUpdateDto) {
        return userMapper.toDto(userRepository.save(userMapper.updateEntity(getById(id),userUpdateDto)));
    }

    @Override
    public void delete(String id) {
           userRepository.delete(getById(id));
    }

    @Override
    public String createToken(TokenRequest tokenRequest) {
        User user = loadUserByUsername(tokenRequest.getUsername());
        if (!passwordEncoder.matches(tokenRequest.getPassword(), user.getPassword())) {

            throw new BizException(ExceptionType.USER_PASSWORD_NOT_MATCH);
        }
        if (!user.isEnabled()){
            throw new BizException(ExceptionType.USER_NOT_ENABLE);
        }
        if (!user.isAccountNonLocked()){
            throw new BizException(ExceptionType.USER_LOCKED);
        }

        return JWT.create()
                //增加主题
                .withSubject(user.getUsername())
                //增加过期时间
                .withExpiresAt(new Date(System.currentTimeMillis()+ SecurityConfig.EXPIRATION_TIME))
                //token签名
                .sign(Algorithm.HMAC512(SecurityConfig.SECRET.getBytes()));

    }

    @Override
    public UserDto getCurrentUser() {
        return userMapper.toDto(super.getCurrentUserEntity());
    }

    private void checkUserName(String username){
        Optional<User> user = userRepository.findByUsername(username);
        if (user.isPresent()){
            throw new BizException(ExceptionType.USER_DUPLICATE_ERROR);
        }
    }


}
